import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
import { EAEnvironmentService } from '@shared';
import { NzFormatEmitEvent, NzTreeComponent, NzTreeNode } from 'ng-zorro-antd/tree';
import { SystemService } from '../../../services/system.service';
// TODO 父节点修改  更新子节点权限点
@Component({
  selector: 'app-menu-tree',
  templateUrl: './menu-tree.component.html',
  styleUrls: ['./menu-tree.component.less']
})
export class MenuTreeComponent implements OnInit, OnChanges {
  @ViewChild('nzTreeComponent', { static: false }) nzTreeComponent!: NzTreeComponent;
  origin: any = { buttonInfoList: [], dictList: [] };
  node!: NzTreeNode;
  functionList: any[] = [];
  @Input() source = '';
  @Input() appId = this.envSrv.env.appId;
  @Input() isAuthorityIdDTOList: AuthorityIdVO[] = [];
  @Input() authorityAssistId: string[] = [];
  @Output() changeData = new EventEmitter<any>();

  _apiAuthSet = new Set<string>(); // 操作权限全数据源
  _NodeAuthMap = new Map<string, AuthorityIdVO>(); // 树权限数据源
  constructor(public service: SystemService, private cdr: ChangeDetectorRef, private envSrv: EAEnvironmentService) {}
  ngOnChanges(changes: SimpleChanges): void {
    if (changes.isAuthorityIdDTOList) {
      // 遍历初始化树节点权限数据源  初始化操作权限数据源
      this.isAuthorityIdDTOList?.forEach(auth => {
        this._NodeAuthMap.set(auth.authorityId, auth);
        if (auth.buttonAuthorityIds) {
          auth.buttonAuthorityIds.forEach((buttonId: string) => this._apiAuthSet.add(buttonId));
        }
      });
    }
  }

  ngOnInit() {
    this.getAllFunction();
  }

  getAllFunction() {
    this.service
      .request(this.service.$api_getAllFunctionInfoByAppId, { appId: this.appId || this.envSrv.env.appId }, 'POST', true, 'FORM')
      .subscribe(res => {
        this.functionList = res;
        // 重赋值选中权限
        this.authorityAssistId = [...this.authorityAssistId];
        this.cdr.detectChanges();
      });
  }

  butCheckedAction(
    status: boolean,
    origin: { buttonInfoList: any[]; [key: string]: any },
    node: NzTreeNode,
    item: { functionButtonId: string }
  ) {
    // 更新完整操作权限数据
    if (status) {
      this._apiAuthSet.add(item.functionButtonId);
    } else {
      this._apiAuthSet.delete(item.functionButtonId);
    }
    origin._selected = false;
    let isHasChecked = false;
    const checkedButIds = []; // 当前操作权限中勾选的权限
    // 判断当前操作权限列表的全选状态
    for (let index = 0; index < origin.buttonInfoList.length; index++) {
      const but = origin.buttonInfoList[index];
      if (this._apiAuthSet.has(but.functionButtonId)) {
        isHasChecked = true;
        checkedButIds.push(but.functionButtonId);
      }
    }

    // 更新树节点选中状态
    if (checkedButIds?.length > 0) {
      origin.checked = true;
      // TODO 去重
      const auths = [...this.authorityAssistId];
      auths.push(origin.id);
      const authsSet = new Set<string>(auths);
      this.authorityAssistId = [...Array.from(authsSet)];
      // 更新菜单权限数据源
      this._NodeAuthMap.set(origin.id, { authorityId: origin.id, buttonAuthorityIds: checkedButIds, isUpdateAuthority: 1 });
    } else {
      origin.checked = false;
      this.authorityAssistId = this.authorityAssistId.filter(auth => auth !== origin.id);
      this._NodeAuthMap.delete(origin.id);
      this.recursionDeleteParantNode(node);
    }
  }

  /**
   * 点击树节点事件
   * @param event
   */
  clickTreeNodeAction(event: any): void {
    this.origin = event.node.origin;
    this.node = event.node;

    // 叶子节点获取操作权限， 非叶子节点则展开
    if (event.node.origin.isLeaf) {
      this.initButtonList(event.node.key, event.node.origin);
    } else {
      event.node.isExpanded = !event.node.isExpanded;
    }
  }

  // 勾选叶子节点菜单时同步处理按钮权限数据
  changeTreeCheckEvent(event: NzFormatEmitEvent | { eventName: string; node: NzTreeNode; keys: string[]; checkedKeys: NzTreeNode[] }) {
    // 叶子节点
    if (event.node?.origin.isLeaf) {
      // 如果当前操作权限列表为该树节点的，则直接勾选
      if (this.origin.id === event.node?.origin.id) {
        this.updateDataSource(event.node?.isChecked!, this.origin.buttonInfoList, event.node?.origin, event.node);
      } else {
        this.service.request(this.service.$api_getFunctionButtonInfo, { id: event.node?.origin.id }).subscribe((res: any[]) => {
          if (res) {
            this.updateDataSource(event.node?.isChecked!, res, event.node?.origin, event.node!);
          }
        });
      }
    } else {
      if (event.node?.isChecked) {
        this.recursionSetNodeAuth(event.node.origin);
        if (event.node.parentNode) {
          this._NodeAuthMap.set(event.node.parentNode.origin.id, {
            authorityId: event.node.parentNode.origin.id,
            buttonAuthorityIds: [],
            isUpdateAuthority: 1
          });
        }
        if (this.origin.checked) {
          this.origin.buttonInfoList.forEach((auth: any) => this._apiAuthSet.add(auth.functionButtonId));
        }
      } else {
        this.recursionDeleteNodeAuth(event.node?.origin);
        if (!this.origin.checked) {
          this.origin.buttonInfoList.forEach((auth: any) => this._apiAuthSet.delete(auth.functionButtonId));
        }
      }
    }
  }

  /**
   * TODO
   * 根据树勾选状态更新数据源
   * 1.更新操作权限点数据源 _apiAuthSet
   * 2.更新菜单权限数据源 _NodeAuthMap
   *
   * @param isChecked
   * @param data
   */
  private updateDataSource(isChecked: boolean, data: any[], origin: any, node: NzTreeNode) {
    if (isChecked) {
      data.forEach(auth => this._apiAuthSet.add(auth.functionButtonId));
      const _auth = this._NodeAuthMap.get(origin.id);
      this._NodeAuthMap.set(origin.id, {
        authorityId: origin.id,
        buttonAuthorityIds: _auth?.buttonAuthorityIds || [],
        isUpdateAuthority: 1
      });
      const auths = [...this.authorityAssistId];
      auths.push(origin.id);
      const authsSet = new Set<string>(auths);
      this.authorityAssistId = [...Array.from(authsSet)];
      this.recursionAddParantNode(node);
    } else {
      data.forEach(auth => this._apiAuthSet.delete(auth.functionButtonId));
      this._NodeAuthMap.delete(origin.id);
      this.authorityAssistId = this.authorityAssistId.filter(auth => auth !== origin.id);
      this.recursionDeleteParantNode(node);
    }
  }

  washTree() {
    const authority: any[] = [];
    this._NodeAuthMap.forEach(nodeAuth => authority.push(nodeAuth));
    const result = {
      authority: authority,
      authorityAssistId: this.authorityAssistId
    };
    this.changeData.emit(result);
    return result;
  }

  initButtonList(id: any, origin: any) {
    this.service.request(this.service.$api_getFunctionButtonInfo, { id }).subscribe((res: any[]) => {
      if (res) {
        origin.buttonInfoList = res;
        origin.all = false;
        // 如果树节点未勾选  剔除源数据中该节点的权限数据
        if (!origin.checked) {
          res.forEach(auth => this._apiAuthSet.delete(auth.functionButtonId));
        }
        if (origin._selected) {
          res.forEach(auth => this._apiAuthSet.add(auth.functionButtonId));
        }
      }
    });
  }

  /**
   * 向下递归添加子节点到树权限数据源
   *
   * @param origin
   */
  private recursionSetNodeAuth(origin: any) {
    this._NodeAuthMap.set(origin.id, { authorityId: origin.id, buttonAuthorityIds: [], isUpdateAuthority: 1 });
    let auths = [...this.authorityAssistId];
    origin.children?.forEach((node: any) => {
      auths.push(node.id);
      // 标记为 通过父级勾选关联导致勾选。防止父级勾选导致更新了源数据
      node._selected = true;
      const _auth = this._NodeAuthMap.get(node.id);
      this._NodeAuthMap.set(node.id, {
        authorityId: node.id,
        buttonAuthorityIds: _auth?.buttonAuthorityIds || [],
        isUpdateAuthority: 1
      });
      if (node?.children?.length > 0) {
        this.recursionSetNodeAuth(node);
      }
    });
    auths = [...auths, ...this.authorityAssistId];
    const authsSet = new Set<string>(auths);
    this.authorityAssistId = [...Array.from(authsSet)];
  }

  private recursionDeleteNodeAuth(origin: any) {
    this._NodeAuthMap.delete(origin.id);
    this.authorityAssistId = this.authorityAssistId.filter(auth => auth !== origin.id);
    origin.children?.forEach((node: any) => {
      this.authorityAssistId = this.authorityAssistId.filter(auth => auth !== node.id);
      this._NodeAuthMap.delete(node.id);
      if (node?.children?.length > 0) {
        this.recursionDeleteNodeAuth(node);
      }
    });
  }

  /**
   * 向上递归取消父节点勾选
   * 清理勾选数据
   *
   * @param node
   */
  private recursionDeleteParantNode(node: NzTreeNode) {
    this.authorityAssistId = this.authorityAssistId.filter(auth => auth !== node.origin.id);
    if (node.parentNode) {
      if (!node.parentNode.children.find(node => node.isChecked) && node.parentNode.origin.level !== 0) {
        this._NodeAuthMap.delete(node.parentNode.origin.id);
      }
      this.recursionDeleteParantNode(node.parentNode);
    }
  }

  /**
   * 向上递归添加父节点到源数据
   * 清理勾选数据
   *
   * @param node
   */
  private recursionAddParantNode(node: NzTreeNode) {
    this._NodeAuthMap.set(node.origin.id, {
      authorityId: node.origin.id,
      buttonAuthorityIds: [],
      isUpdateAuthority: 1
    });
    if (node.parentNode) {
      this.recursionAddParantNode(node.parentNode);
    }
  }
}

export interface AuthorityIdVO {
  authorityId: string;
  buttonAuthorityIds: string[];
  dataAuthority?: { dictId: number; dictItemId: number; itemKey: string }[];
  isUpdateAuthority?: 0 | 1;
}
